# -*- coding: utf-8 -*-
"""
健康模块的 Celery 任务
"""
import logging
from celery import shared_task
from django.utils import timezone
from django.db import transaction
from .models import Post, SensitiveWord
from services.spider import news_crawler, words_crawler
from services.checker import SensitiveWordTrieDetector

logger = logging.getLogger(__name__)

# 创建全局 Trie 树检测器实例
_trie_detector = None

def get_trie_detector():
    """获取全局 Trie 树敏感词检测器实例"""
    global _trie_detector
    if _trie_detector is None:
        _trie_detector = SensitiveWordTrieDetector()
        _trie_detector.initialize()
    return _trie_detector

def check_sensitive_words(content):
    """
    使用 Trie 树检查内容是否包含敏感词
    :param content: 要检查的文本内容
    :return: (是否包含敏感词, 敏感词列表)
    """
    detector = get_trie_detector()
    try:
        return detector.detect(content)
    except Exception as e:
        # 如果 Trie 树未初始化或出错，回退到基本检测方法
        logger.error(f"Trie detection failed: {e}")
        return False, []

@shared_task(bind=True, max_retries=2, default_retry_delay=30, soft_time_limit=60, time_limit=120)
def review_post_task(self, post_id):
    """
    异步审核帖子任务
    :param post_id: 帖子ID
    """
    try:
        # 获取帖子对象
        post = Post.objects.get(id=post_id)
        
        # 如果帖子已经是审核状态，则跳过
        if post.status != 'review':
            logger.info(f"Post {post_id} is not in review status, current status: {post.status}")
            return
            
        # 检查标题和内容中的敏感词
        has_sensitive_title, sensitive_title_words = check_sensitive_words(post.title)
        has_sensitive_content, sensitive_content_words = check_sensitive_words(post.content)
        
        # 合并敏感词列表
        all_sensitive_words = list(set(sensitive_title_words + sensitive_content_words))
        
        # 根据敏感词检查结果更新帖子状态
        with transaction.atomic():
            if has_sensitive_title or has_sensitive_content:
                # 如果包含敏感词，将帖子状态设置为'banned'（已封禁）
                post.status = 'banned'
                logger.warning(f"Post {post_id} contains sensitive words: {', '.join(all_sensitive_words)}")
            else:
                # 如果不包含敏感词，将帖子状态设置为'published'（已发布）
                post.status = 'published'
                logger.info(f"Post {post_id} passed review and is now published")
            
            # 更新帖子
            post.save()
            
        logger.info(f"Post {post_id} review completed, new status: {post.status}")
        
    except Post.DoesNotExist:
        logger.error(f"Post {post_id} does not exist")
    except Exception as e:
        logger.error(f"Error reviewing post {post_id}: {e}")
        # 检查是否应该重试
        if self.request.retries < self.max_retries:
            logger.info(f"Retrying post review task for post {post_id}, attempt {self.request.retries + 1}")
            raise self.retry(exc=e, countdown=self.default_retry_delay)
        else:
            logger.error(f"Post review task failed after {self.max_retries} retries for post {post_id}")
            raise

@shared_task(bind=True, max_retries=2, default_retry_delay=60, soft_time_limit=600, time_limit=900)
def news_crawler_task(self):
    """
    健康资讯爬虫任务
    """
    try:
        logger.info("Starting news crawler task")
        news_crawler()
        logger.info("News crawler task completed successfully")
    except Exception as e:
        logger.error(f"Error in news crawler task: {e}")
        # 检查是否应该重试
        if self.request.retries < self.max_retries:
            logger.info(f"Retrying news crawler task, attempt {self.request.retries + 1}")
            raise self.retry(exc=e, countdown=self.default_retry_delay)
        else:
            logger.error(f"News crawler task failed after {self.max_retries} retries")
            raise


@shared_task(bind=True, max_retries=2, default_retry_delay=60, soft_time_limit=600, time_limit=900)
def words_crawler_task(self):
    """
    敏感词更新任务
    """
    try:
        logger.info("Starting words crawler task")
        words_crawler()
        logger.info("Words crawler task completed successfully")
    except Exception as e:
        logger.error(f"Error in words crawler task: {e}")
        # 检查是否应该重试
        if self.request.retries < self.max_retries:
            logger.info(f"Retrying words crawler task, attempt {self.request.retries + 1}")
            raise self.retry(exc=e, countdown=self.default_retry_delay)
        else:
            logger.error(f"Words crawler task failed after {self.max_retries} retries")
            raise


@shared_task(bind=True, max_retries=2, default_retry_delay=120, soft_time_limit=1800, time_limit=2400)
def daily_health_analysis_task(self):
    """
    每日健康数据分析任务
    """
    try:
        logger.info("Starting daily health analysis task")
        
        from .models import HealthReport, BodyRecord, EatingRecord, SleepRecord, SportsRecord
        from services.report_llm import analyze_health_data
        from django.contrib.auth import get_user_model
        from django.utils import timezone
        from datetime import timedelta
        
        User = get_user_model()
        
        # 获取所有用户
        users = User.objects.all()
        
        # 计算昨天的日期
        yesterday = timezone.now().date() - timedelta(days=1)
        
        for user in users:
            try:
                # 获取用户昨天的健康数据（精确匹配昨天的日期）
                body_records = BodyRecord.objects.filter(user_id=user.id, created_at__date=yesterday)
                eating_records = EatingRecord.objects.filter(user_id=user.id, created_at__date=yesterday)
                sleep_records = SleepRecord.objects.filter(user_id=user.id, created_at__date=yesterday)
                sports_records = SportsRecord.objects.filter(user_id=user.id, created_at__date=yesterday)
                
                # 如果用户有健康数据，则进行分析
                if body_records.exists() or eating_records.exists() or sleep_records.exists() or sports_records.exists():
                    health_data = {
                        'body_records': list(body_records.values()),
                        'eating_records': list(eating_records.values()),
                        'sleep_records': list(sleep_records.values()),
                        'sports_records': list(sports_records.values())
                    }
                    
                    # 调用大模型进行分析
                    analysis_result = analyze_health_data(health_data)
                    
                    # 保存分析结果到数据库
                    # 查找用户最新的体检报告
                    latest_report = HealthReport.objects.filter(user_id=user.id).order_by('-uploaded_at').first()
                    
                    if latest_report:
                        # 更新现有报告的分析结果
                        latest_report.analysis_result = analysis_result
                        latest_report.save()
                    else:
                        # 创建新的体检报告记录
                        HealthReport.objects.create(
                            user_id=user.id,
                            file_path='',
                            analysis_result=analysis_result
                        )
                    
                    logger.info(f"Daily health analysis completed for user {user.id}")
                else:
                    logger.info(f"No health data found for user {user.id}")
                    
            except Exception as e:
                logger.error(f"Error analyzing health data for user {user.id}: {e}")
                continue
                
        logger.info("Daily health analysis task completed successfully")
    except Exception as e:
        logger.error(f"Error in daily health analysis task: {e}")
        # 检查是否应该重试
        if self.request.retries < self.max_retries:
            logger.info(f"Retrying daily health analysis task, attempt {self.request.retries + 1}")
            raise self.retry(exc=e, countdown=self.default_retry_delay)
        else:
            logger.error(f"Daily health analysis task failed after {self.max_retries} retries")
            raise


@shared_task(bind=True, max_retries=3, default_retry_delay=60, soft_time_limit=300, time_limit=600)
def analyze_health_report_task(self, report_id):
    """
    分析体检报告任务 - 简化版本，不进行流式更新
    :param report_id: 体检报告ID
    """
    try:
        logger.info(f"Starting health report analysis task for report {report_id}")
        
        from .models import HealthReport
        from services.report_llm import get_report_suggestion
        import os
        from django.conf import settings
        
        # 获取体检报告
        try:
            report = HealthReport.objects.get(id=report_id)
        except HealthReport.DoesNotExist:
            logger.error(f"Health report {report_id} does not exist")
            return
            
        # 构造文件路径
        file_path = os.path.join(settings.MEDIA_ROOT, report.file_path)
        
        # 检查文件是否存在
        if not os.path.exists(file_path):
            logger.error(f"Health report file does not exist: {file_path}")
            # 更新状态为分析失败
            report.status = 'failed'
            report.analysis_result = "体检报告文件不存在"
            report.save()
            return
            
        # 调用大模型进行分析
        try:
            # 更新报告状态为分析中
            report.status = 'analyzing'
            report.save()
            
            # 获取分析结果（非流式版本）
            full_result = get_report_suggestion(file_path)
            
            # 保存最终分析结果并更新状态
            report.analysis_result = full_result
            report.status = 'completed'
            report.save()
            
            logger.info(f"Health report analysis completed for report {report_id}")
        except Exception as e:
            logger.error(f"Error analyzing health report {report_id}: {e}")
            # 更新报告状态为分析失败
            report.status = 'failed'
            report.analysis_result = f"分析失败: {str(e)}"
            report.save()
            
    except Exception as e:
        logger.error(f"Error in health report analysis task: {e}")
        # 检查是否应该重试
        if self.request.retries < self.max_retries:
            logger.info(f"Retrying health report analysis task for report {report_id}, attempt {self.request.retries + 1}")
            raise self.retry(exc=e, countdown=self.default_retry_delay)
        else:
            logger.error(f"Health report analysis task failed after {self.max_retries} retries for report {report_id}")
            # 更新报告状态为分析失败
            try:
                report = HealthReport.objects.get(id=report_id)
                report.status = 'failed'
                report.analysis_result = f"分析失败: 任务重试{self.max_retries}次后仍然失败"
                report.save()
            except Exception:
                pass
            raise